package com.xingu.xg.service.impl;

import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.sun.source.tree.Tree;
import com.xingu.xg.domain.TreeNode;
import com.xingu.xg.dto.AddNodeQuery;
import com.xingu.xg.dto.CopyNodeQuery;
import com.xingu.xg.dto.DeleteNodeQuery;
import com.xingu.xg.service.TreeNodeService;
import com.xingu.xg.mapper.TreeNodeMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

/**
* @author liyanzhen
* @description 针对表【tree_node】的数据库操作Service实现
* @createDate 2025-04-15 11:24:38
*/
@Service
public class TreeNodeServiceImpl extends ServiceImpl<TreeNodeMapper, TreeNode>
    implements TreeNodeService{

    @Autowired
    private TreeNodeService service;

    @Override
    public void create(AddNodeQuery addNodeQuery) {
        int createType = addNodeQuery.getCreateType();
        switch (createType){
            case 1:
                this.createBefore(addNodeQuery);
                break;
            case 2:
                this.createAfter(addNodeQuery);
                break;
            case 3:
                this.createIn(addNodeQuery);
                break;
            case 4:
                this.createParent(addNodeQuery);
                break;
            default:
                throw new RuntimeException("服务器需要知道您想要把新节点创建到哪里");
        }
    }

    @Transactional(rollbackFor = Exception.class)
    public void createParent(AddNodeQuery addNodeQuery) {
        TreeNode selectNode = this.baseMapper.selectById(addNodeQuery.getSelectedId());
        if (selectNode == null){
            throw new RuntimeException("数据库不存在操作数据");
        }
        TreeNode treeNode = new TreeNode();
        treeNode.setParentId(treeNode.getParentId());
        LocalDateTime now = LocalDateTime.now();
        treeNode.setCreatedAt(now);
        treeNode.setUpdatedAt(now);
        treeNode.setOrderindex(1.0);
        treeNode.setName(addNodeQuery.getName());
        this.save(treeNode);
        treeNode.setParentId(treeNode.getId());
        this.updateById(selectNode);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void copy(CopyNodeQuery copyNodeQuery) {
        // 查找所有涉及节点
        List<TreeNode> list = this.lambdaQuery().in(TreeNode::getId, copyNodeQuery.getList()).list();
        // 如果没有返回空数组，无需判空，因为list不可能为null
        if (list.isEmpty()){
            throw new RuntimeException("数据库不存在操作数据");
        }
        // id不能重复，无需做重复数据判断处理
        Map<Integer, TreeNode> map = list.stream().collect(Collectors.toMap(TreeNode::getId, v -> v));

        // 获取选择的根节点
        TreeNode root = null;
        for (TreeNode treeNode : list) {
            if (!map.containsKey(treeNode.getParentId())) {
                // 列表中没有它的父节点，则这个节点就是我们要找的需要复制的根节点
                root = treeNode;
                break;
            }
        }

        if (root == null){
            throw new RuntimeException("数据库不存在操作数据或数据库存在循环依赖");
        }

        TreeNode finalRoot = root;
        List<TreeNode> addNodeList = new ArrayList<>();
        LocalDateTime now = LocalDateTime.now();
        Map<Integer, TreeNode> idMapping = new HashMap<>();
        for (TreeNode treeNode : list) {
            TreeNode newTreeNode = new TreeNode();
            newTreeNode.setParentId(treeNode.getParentId());
            newTreeNode.setCreatedAt(now);
            newTreeNode.setUpdatedAt(now);
            newTreeNode.setOrderindex(treeNode.getOrderindex());
            newTreeNode.setName(treeNode.getName());
            addNodeList.add(newTreeNode);
            idMapping.put(treeNode.getId(), newTreeNode);
        }
        // 保存所有，获取id
        this.saveBatch(addNodeList);

        for (TreeNode treeNode : addNodeList) {
            treeNode.setParentId(idMapping.get(treeNode.getParentId()).getId());
        }

        this.updateBatchById(addNodeList);
    }

    @Override
    @Transactional
    public void deleteBatch(DeleteNodeQuery deleteNodeQuery) {
        List<TreeNode> list = this.lambdaQuery().in(TreeNode::getId, deleteNodeQuery.getDeleteList()).list();
        if (list.isEmpty()){
            throw new RuntimeException("数据库不存在操作数据");
        }

        this.remove(new LambdaUpdateWrapper<TreeNode>()
                .in(TreeNode::getId, list.stream().map(TreeNode::getId).collect(Collectors.toList())));

        for (TreeNode treeNode : list) {
            this.lambdaUpdate()
                    .eq(TreeNode::getParentId, treeNode.getId())
                    .set(TreeNode::getParentId, treeNode.getParentId())
                    .update();
        }
    }

    private void createIn(AddNodeQuery addNodeQuery) {
        double orderIndex = this
                .lambdaQuery()
                .eq(TreeNode::getParentId, addNodeQuery.getSelectedId())
                .list()
                .stream()
                .map(TreeNode::getOrderindex)
                .max(Double::compareTo)
                .orElse(1.0);
        TreeNode treeNode = new TreeNode();
        treeNode.setParentId(addNodeQuery.getSelectedId());
        LocalDateTime now = LocalDateTime.now();
        treeNode.setCreatedAt(now);
        treeNode.setUpdatedAt(now);
        treeNode.setOrderindex(orderIndex);
        treeNode.setName(addNodeQuery.getName());
        this.save(treeNode);
    }

    private void createAfter(AddNodeQuery addNodeQuery) {
        List<TreeNode> list = this
                .lambdaQuery()
                .ge(TreeNode::getId, addNodeQuery.getSelectedId())
                .orderByAsc(TreeNode::getId)
                .last("limit 2")
                .list();
        double orderIndex = 1.0;
        if (list.size() == 2){
            orderIndex = (list.get(0).getOrderindex() + list.get(1).getOrderindex())/2;
        }else if (list.size() == 1){
            // 第一个元素之后
            orderIndex = list.get(0).getOrderindex() + 1;
        }
        if (list.isEmpty() || !Objects.equals(list.get(0).getId(), addNodeQuery.getSelectedId())){
            throw new RuntimeException("数据库不存在操作数据");
        }
        TreeNode parent = list.get(0);
        TreeNode treeNode = new TreeNode();
        treeNode.setParentId(parent.getId());
        LocalDateTime now = LocalDateTime.now();
        treeNode.setCreatedAt(now);
        treeNode.setUpdatedAt(now);
        treeNode.setOrderindex(orderIndex);
        treeNode.setName(addNodeQuery.getName());
        this.save(treeNode);
    }

    private void createBefore(AddNodeQuery addNodeQuery) {
        List<TreeNode> list = this
                .lambdaQuery()
                .le(TreeNode::getId, addNodeQuery.getSelectedId())
                .orderByDesc(TreeNode::getId)
                .last("limit 2")
                .list();
        double orderIndex = 1.0;
        if (list.size() == 2){
            orderIndex = (list.get(0).getOrderindex() + list.get(1).getOrderindex())/2;
        }else if (list.size() == 1){
            // 第一个元素之前
            orderIndex = list.get(0).getOrderindex()/2;
        }
        if (list.isEmpty() || !Objects.equals(list.get(0).getId(), addNodeQuery.getSelectedId())){
            throw new RuntimeException("数据库不存在操作数据");
        }
        TreeNode parent = list.get(0);
        TreeNode treeNode = new TreeNode();
        treeNode.setParentId(parent.getId());
        LocalDateTime now = LocalDateTime.now();
        treeNode.setCreatedAt(now);
        treeNode.setUpdatedAt(now);
        treeNode.setOrderindex(orderIndex);
        treeNode.setName(addNodeQuery.getName());
        this.save(treeNode);
    }
}




